<template>
  <div class="todo-content" v-if="store.todo">
    <div class="header">
      <div class="container">
        <div class="header-left">
          <CheckBox
            @click="emit('isDoneToggle', store.todo)"
            :disabled="props.disable"
            v-model:checked="store.todo.isDone"
          ></CheckBox>
          <div class="separator"></div>
          <DatePicker
            :disabled="props.disable"
            @change="handleDateChange"
            v-model:value="deadlineDate"
            :allow-clear="false"
            placeholder="请选择截止时间"
            :format="customFormat"
            :class="`${isExpired ? 'is-expired' : 'not-expired'}`"
          ></DatePicker>
        </div>
        <div class="header-right">
          <i></i>
        </div>
      </div>
    </div>
    <div class="main">
      <div class="container">
        <div class="content">
          <div class="title-input">
            <input
              :disabled="props.disable"
              @input="handleTodoTitleUpdate($event)"
              :value="store.todo.title"
              type="text"
            />
          </div>
          <!-- 移除固定工具栏 -->
          <div class="content-input">
            <editor-content class="content-editor" :editor="editor" />
          </div>

          <!-- 浮动菜单 -->
          <div v-if="showMenu" class="floating-menu" :style="menuPosition">
            <div class="menu-item" @click="applyCommand('bold')">
              <i class="ri-bold"></i>
              <span>加粗</span>
            </div>
            <div class="menu-item" @click="applyCommand('italic')">
              <i class="ri-italic"></i>
              <span>斜体</span>
            </div>
            <div class="menu-item" @click="applyCommand('strike')">
              <i class="ri-strikethrough"></i>
              <span>删除线</span>
            </div>
            <div class="menu-item" @click="applyCommand('heading1')">
              <i class="ri-h-1"></i>
              <span>标题1</span>
            </div>
            <div class="menu-item" @click="applyCommand('heading2')">
              <i class="ri-h-2"></i>
              <span>标题2</span>
            </div>
            <div class="menu-item" @click="applyCommand('bulletList')">
              <i class="ri-list-unordered"></i>
              <span>无序列表</span>
            </div>
            <div class="menu-item" @click="applyCommand('orderedList')">
              <i class="ri-list-ordered"></i>
              <span>有序列表</span>
            </div>
            <div class="menu-item" @click="applyCommand('codeBlock')">
              <i class="ri-code-box-line"></i>
              <span>代码块</span>
            </div>
            <div class="menu-item" @click="applyCommand('blockquote')">
              <i class="ri-double-quotes-l"></i>
              <span>引用</span>
            </div>
            <div class="menu-item" @click="applyCommand('horizontalRule')">
              <i class="ri-separator"></i>
              <span>分割线</span>
            </div>
            <div class="menu-item" @click="applyCommand('link')">
              <i class="ri-link"></i>
              <span>链接</span>
            </div>
            <div class="menu-item" @click="applyCommand('table')">
              <i class="ri-table-2"></i>
              <span>表格</span>
            </div>
            <div class="menu-item" @click="applyCommand('image')">
              <i class="ri-image-line"></i>
              <span>图片</span>
            </div>
            <!-- <div class="menu-item" @click="applyCommand('file')">
              <i class="ri-file-line"></i>
              <span>文件</span>
            </div> -->
          </div>

          <!-- 隐藏的文件上传输入 -->
          <input
            type="file"
            id="image-upload"
            @change="uploadImage"
            accept="image/*"
            style="display: none"
            ref="imageInput"
          />
          <input
            type="file"
            id="file-upload"
            @change="uploadFile"
            style="display: none"
            ref="fileInput"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import CheckBox from '@renderer/components/CheckBox.vue'
import todoStore from '@renderer/store/todo'
//@ts-ignore
import Highlight from '@tiptap/extension-highlight'
//@ts-ignore
import Typography from '@tiptap/extension-typography'
import StarterKit from '@tiptap/starter-kit'
import { DatePicker } from 'ant-design-vue'
import Link from '@tiptap/extension-link'
import { Editor, EditorContent } from '@tiptap/vue-3'
import { computed, onMounted, ref, watch, nextTick } from 'vue'
import dayjs, { Dayjs } from 'dayjs'
// 导入新的扩展
import Table from '@tiptap/extension-table'
import TableRow from '@tiptap/extension-table-row'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'
import Image from '@tiptap/extension-image'
import Placeholder from '@tiptap/extension-placeholder'
import { Modal } from 'ant-design-vue'
import { Extension } from '@tiptap/core'
// 导入代码高亮相关扩展
import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'
// 修改 lowlight 的导入方式
import { common, createLowlight } from 'lowlight'
// 创建 lowlight 实例
const lowlight = createLowlight(common)

// 导入需要支持的语言
import javascript from 'highlight.js/lib/languages/javascript'

// 注册语言
lowlight.register('javascript', javascript)

const store = todoStore()

const props = defineProps({
  disable: {
    type: Boolean,
    default: false
  }
})

document.addEventListener('paste', (e) => {
  e.stopImmediatePropagation()
})

const editor = ref<Editor>()
const imageInput = ref<HTMLInputElement | null>(null)
const fileInput = ref<HTMLInputElement | null>(null)
const showMenu = ref(false)
const menuPosition = ref({
  top: '0px',
  left: '0px'
})

// 创建自定义扩展来处理键盘事件
const SlashMenuExtension = Extension.create({
  name: 'slashMenu',

  addKeyboardShortcuts() {
    return {
      '/': () => {
        // 获取当前光标位置
        const { editor } = this
        const { view } = editor
        const { state } = view
        const { selection } = state
        const { $anchor } = selection

        // 检查光标是否在行首
        const isAtLineStart = $anchor.pos === $anchor.start()

        // 只有在行首时才显示菜单
        if (!isAtLineStart) {
          return false
        }

        // 获取光标在视图中的坐标
        const coords = view.coordsAtPos($anchor.pos)

        // 设置菜单位置
        menuPosition.value = {
          top: `${coords.bottom}px`,
          left: `${coords.left}px`
        }

        // 确保菜单不超出窗口边界
        nextTick(() => {
          const menu = document.querySelector('.floating-menu') as HTMLElement
          if (!menu) return

          const menuRect = menu.getBoundingClientRect()
          const windowWidth = window.innerWidth
          const windowHeight = window.innerHeight

          if (menuRect.right > windowWidth) {
            menuPosition.value.left = `${windowWidth - menuRect.width}px`
          }

          if (menuRect.bottom > windowHeight) {
            menuPosition.value.top = `${windowHeight - menuRect.height}px`
          }
        })

        // 显示菜单
        showMenu.value = true

        return true // 返回 true 表示我们已处理此键盘事件
      }
    }
  }
})

const deadlineDate = ref<Dayjs>(dayjs())

const isExpired = computed(() => {
  const dateValue = ref(dayjs())
  return dateValue.value.isAfter(store.todo?.deadlineDate)
})

const emit = defineEmits(['isDoneToggle'])

const customFormat = (value) => {
  const today = dayjs().startOf('day')
  const targetDate = value.startOf('day')
  const diffDays = targetDate.diff(today, 'day')

  if (diffDays === 0) {
    return `今天, ${value.format('M月D日')}`
  } else if (diffDays === -1) {
    return `昨天, ${value.format('M月D日')}`
  } else if (diffDays === 1) {
    return `明天, ${value.format('M月D日')}`
  } else if (diffDays === -2) {
    return `前天, ${value.format('M月D日')}`
  } else if (diffDays === 2) {
    return `后天, ${value.format('M月D日')}`
  } else if (targetDate.isSame(today, 'week')) {
    // 在本周内，但不是前天、昨天、今天、明天、后天
    return `${value.format('dddd, M月D日')}`.replace('星期', '周')
  } else if (targetDate.isSame(today.add(1, 'week'), 'week')) {
    // 在下周内
    return `下${value.format('dddd, M月D日')}`.replace('星期', '周')
  } else if (diffDays > 0) {
    // 超过下周
    const remainingDays = targetDate.diff(today, 'day')
    return `${value.format('M月D日')}, 剩余${remainingDays}天`
  } else if (diffDays < 0) {
    // 超过上周
    const delayedDays = Math.abs(diffDays)
    return `${value.format('M月D日')}, 延期${delayedDays}天`
  }
  return `${value.format('M月D日')}`
}

const handleDateChange = (date) => {
  deadlineDate.value = dayjs(date).endOf('day')
  if (store.todo) {
    store.todo.deadlineDate = deadlineDate.value
      .toDate()
      .toLocaleString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: false
      })
      .replace(/\//g, '-')
    window.api.updateTodoData({
      ...store.todo
    })
  }
}

const handleTodoTitleUpdate = (e) => {
  if (store.todo) {
    store.todo.title = e.target.value
    window.api.updateTodoData({
      ...store.todo
    })
  }
}

watch(
  () => store.todo,
  () => {
    editor.value?.commands.setContent(store.todo?.content || '')
  }
)

watch(
  () => store.todo?.deadlineDate,
  () => {
    deadlineDate.value = dayjs(store.todo?.deadlineDate)
  }
)

// 应用命令
const applyCommand = (command) => {
  if (!editor.value) return

  switch (command) {
    case 'bold':
      editor.value.chain().focus().toggleBold().run()
      break
    case 'italic':
      editor.value.chain().focus().toggleItalic().run()
      break
    case 'strike':
      editor.value.chain().focus().toggleStrike().run()
      break
    case 'heading1':
      editor.value.chain().focus().toggleHeading({ level: 1 }).run()
      break
    case 'heading2':
      editor.value.chain().focus().toggleHeading({ level: 2 }).run()
      break
    case 'bulletList':
      editor.value.chain().focus().toggleBulletList().run()
      break
    case 'orderedList':
      editor.value.chain().focus().toggleOrderedList().run()
      break
    case 'codeBlock':
      editor.value.chain().focus().toggleCodeBlock().run()
      break
    case 'blockquote':
      editor.value.chain().focus().toggleBlockquote().run()
      break
    case 'horizontalRule':
      editor.value.chain().focus().setHorizontalRule().run()
      break
    case 'link':
      setLink()
      break
    case 'table':
      insertTable()
      break
    case 'image':
      imageInput.value?.click()
      break
    // case 'file':
    //   fileInput.value?.click()
    //   break
  }

  // 关闭菜单
  showMenu.value = false
}

// 设置链接
const setLink = () => {
  // 设置链接
  editor.value
    ?.chain()
    .focus()
    .setLink({
      href: ''
    })
    .run()
}

// 插入表格
const insertTable = () => {
  editor.value?.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
}

// 上传图片
const uploadImage = async (event) => {
  const file = event.target.files[0]
  if (!file) return

  try {
    const reader = new FileReader()
    reader.onload = (e) => {
      const imageUrl = e.target?.result
      if (imageUrl && typeof imageUrl === 'string') {
        editor.value?.chain().focus().setImage({ src: imageUrl, alt: file.name }).run()
      }
    }
    reader.readAsDataURL(file)

    // 清空input，以便可以再次选择同一文件
    event.target.value = ''
  } catch (error) {
    Modal.error({
      title: '上传失败',
      content: '图片上传失败，请重试'
    })
  }
}

// 上传文件
const uploadFile = async (event) => {
  const file = event.target.files[0]
  if (!file) return

  try {
    const fileUrl = `#${file.name}` // 这里应该是真实的URL

    // 插入文件链接
    editor.value
      ?.chain()
      .focus()
      .setLink({
        href: fileUrl,
        target: '_blank'
      })
      .insertContent(file.name)
      .run()

    // 清空input，以便可以再次选择同一文件
    event.target.value = ''
  } catch (error) {
    console.error('上传文件失败:', error)
    Modal.error({
      title: '上传失败',
      content: '文件上传失败，请重试'
    })
  }
}

onMounted(() => {
  editor.value = new Editor({
    extensions: [
      // 替换 StarterKit 中的 codeBlock 扩展
      StarterKit.configure({
        codeBlock: false // 禁用默认的代码块扩展
      }),
      Typography,
      Highlight,
      Link.configure({
        openOnClick: false, // 点击链接时不自动打开
        HTMLAttributes: {
          target: '_blank',
          rel: 'noopener noreferrer'
        }
      }),
      Table.configure({
        resizable: true
      }),
      TableRow,
      TableHeader,
      TableCell,
      Image.configure({
        allowBase64: true,
        inline: true
      }),
      SlashMenuExtension, // 添加我们的自定义扩展
      // 添加代码高亮扩展
      CodeBlockLowlight.configure({
        lowlight,
        defaultLanguage: 'javascript',
        HTMLAttributes: {
          class: 'hljs'
        }
      }),
      Placeholder.configure({
        placeholder: '输入内容或者使用 / 快速插入'
      })
    ],
    content: store.todo?.content || '',
    editable: !props.disable,

    onBlur(_) {
      const content = editor.value!.getHTML()
      if (store.todo) {
        store.todo.content = content
        window.api.updateTodoData({
          ...store.todo
        })
      }
    }
  })
  document.addEventListener('click', () => {
    showMenu.value = false
  })
  // ... 现有代码 ...
})
</script>

<style scoped lang="scss">
.todo-content {
  width: 400px;
  height: 100%;
  background: var(--xz-card-bg);

  .header {
    border-bottom: 1px solid var(--xz-secondbg);
    width: 100%;
    height: 60px;
    padding: 20px 20px 10px 20px;

    .container {
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: space-between;

      .header-left {
        display: flex;
        align-items: center;
        gap: 10px;

        .separator {
          width: 1px;
          height: 16px;
          background-color: var(--xz-secondbg);
        }
      }
    }
  }

  .main {
    width: 100%;
    height: calc(100% - 60px);

    .container {
      padding: 10px 20px 0px 20px;
      height: 100%;

      .content {
        display: flex;
        flex-direction: column;
        height: 100%;

        .title-input {
          input {
            width: 100%;
            border: none;
            min-height: 40px;
            font-size: 1.2rem;
            font-weight: bold;
            background: none;
            color: var(--xz-fontcolor);
            outline: none;
          }
        }

        .content-input {
          height: 100%;

          .content-editor {
            height: 100%;
          }
        }
      }
    }
  }
}

.is-expired {
  .ant-picker-input {
    input {
      color: red !important;
    }
  }
}

.not-expired {
  .ant-picker-input {
    input {
      color: blue !important;
    }
  }
}

/* 添加工具栏样式 */
.editor-toolbar {
  display: flex;
  flex-wrap: wrap;
  padding: 5px 0;
  border-bottom: 1px solid var(--xz-secondbg);
  margin-bottom: 10px;
}

.editor-toolbar button,
.editor-toolbar label {
  background: none;
  border: 1px solid var(--xz-secondbg);
  border-radius: 4px;
  padding: 4px 8px;
  margin-right: 5px;
  margin-bottom: 5px;
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--xz-fontcolor);
}

.editor-toolbar button:hover,
.editor-toolbar label:hover {
  background-color: var(--xz-secondbg);
}

.editor-toolbar .is-active {
  background-color: var(--xz-secondbg);
  color: var(--xz-primary);
}

.image-upload-btn,
.file-upload-btn {
  display: inline-block;
  cursor: pointer;
}

/* TipTap 编辑器内容样式 */
:deep(.ProseMirror) {
  padding: 10px;
  min-height: 200px;
  outline: none;
  overflow-y: auto;
}

:deep(.ProseMirror p) {
  margin: 0.5em 0;
}

:deep(.ProseMirror table) {
  border-collapse: collapse;
  table-layout: fixed;
  width: 100%;
  margin: 0;
  overflow: hidden;
}

:deep(.ProseMirror table td),
:deep(.ProseMirror table th) {
  min-width: 1em;
  border: 2px solid var(--xz-secondbg);
  padding: 3px 5px;
  vertical-align: top;
  box-sizing: border-box;
  position: relative;
}

:deep(.ProseMirror table th) {
  font-weight: bold;
  background-color: var(--xz-secondbg);
}

:deep(.ProseMirror img) {
  max-width: 100%;
  height: auto;
}

:deep(.ProseMirror blockquote) {
  border: var(--style-border-always);
  background-color: var(--xz-secondbg);
  color: var(--xz-secondtext);
  border-radius: 8px;
  margin: 1rem 0;
  padding: 0.5rem 0.8rem;
}

:deep(.ProseMirror pre) {
  background: var(--xz-secondbg);
  border-radius: 4px;
  padding: 10px;
  overflow-x: auto;
}

/* 添加样式部分 -->
<style scoped lang="scss">
/* ... 现有样式 ... */

/* 浮动菜单样式 - 修改为右键菜单风格 */
.floating-menu {
  position: fixed;
  background: var(--xz-card-bg);
  border-radius: 4px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  min-width: 180px;
  z-index: 1000;
  overflow: hidden;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.menu-item {
  padding: 4px 8px;
  display: flex;
  align-items: center;
  cursor: pointer;
  transition: all 0.3s ease-in-out;
  border-radius: 4px;
}

.menu-item:hover {
  background-color: var(--xz-theme);

  i {
    transition: all 0.3s ease-in-out;
    color: var(--xz-white);
  }

  span {
    transition: all 0.3s ease-in-out;
    color: var(--xz-white);
  }
}

.menu-item i {
  margin-right: 8px;
  font-size: 16px;
}

.menu-item span {
  font-size: 14px;
}

/* 代码块高亮样式 */
:deep(.ProseMirror pre) {
  background: var(--xz-secondbg);
  border-radius: 4px;
  padding: 10px;
  overflow-x: auto;
  margin: 0.5em 0;
}

:deep(.ProseMirror pre code) {
  color: inherit;
  padding: 0;
  background: none;
  font-size: 0.9em;
  font-family: 'Fira Code', 'Consolas', 'Monaco', 'Andale Mono', 'Ubuntu Mono', monospace;
}

/* 高亮.js 主题样式 */
:deep(.hljs-comment),
:deep(.hljs-quote) {
  color: #999;
  font-style: italic;
}

:deep(.hljs-keyword),
:deep(.hljs-selector-tag),
:deep(.hljs-subst) {
  color: #88f;
}

:deep(.hljs-number),
:deep(.hljs-literal),
:deep(.hljs-variable),
:deep(.hljs-template-variable),
:deep(.hljs-tag .hljs-attr) {
  color: #f78c6c;
}

:deep(.hljs-string),
:deep(.hljs-doctag) {
  color: #7ec699;
}

:deep(.hljs-title),
:deep(.hljs-section),
:deep(.hljs-selector-id) {
  color: #82aaff;
  font-weight: bold;
}

:deep(.hljs-subst) {
  font-weight: normal;
}

:deep(.hljs-type),
:deep(.hljs-class .hljs-title) {
  color: #ffcb6b;
}

:deep(.hljs-tag),
:deep(.hljs-name),
:deep(.hljs-attribute) {
  color: #f07178;
}

:deep(.hljs-regexp),
:deep(.hljs-link) {
  color: #c792ea;
}

:deep(.hljs-symbol),
:deep(.hljs-bullet) {
  color: #c792ea;
}

:deep(.hljs-built_in),
:deep(.hljs-builtin-name) {
  color: #82aaff;
}

:deep(.hljs-meta) {
  color: #89ddff;
}

:deep(.hljs-deletion) {
  background: #fdd;
}

:deep(.hljs-addition) {
  background: #dfd;
}

:deep(.hljs-emphasis) {
  font-style: italic;
}

:deep(.hljs-strong) {
  font-weight: bold;
}

:deep(.ProseMirror p.is-editor-empty:first-child::before) {
  content: attr(data-placeholder);
  float: left;
  color: #adb5bd;
  opacity: 0.8;
  pointer-events: none;
  height: 0;
}

/* ... 其他样式 ... */
</style>
